﻿using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.IO;
using System.Reflection;

namespace Stone.Components
{
    public class JsonSerializableList<T> : IJsonSerializable
        where T : IJsonSerializable
    {
        ConstructorInfo constructor;
        IList<T> list;

        public IList<T> List
        {
            get { return list; }
        }

        public JsonSerializableList()
        {
            this.list = new List<T>();

            constructor = typeof(T).GetConstructor(System.Type.EmptyTypes);
        }

        public JsonSerializableList(IList<T> list)
            : this()
        {
            this.list = list;
        }

        #region IJsonSerializable 成员

        public string ToJson(bool formatting)
        {
            StringBuilder sb = new StringBuilder();
            JsonWriter writer = new JsonTextWriter(new StringWriter(sb));
            writer.Formatting = formatting ? Formatting.Indented : Formatting.None;
            WriteJson(writer);
            writer.Flush();
            writer.Close();
            return sb.ToString();
        }

        public virtual void WriteJson(JsonWriter writer)
        {
            writer.WriteStartArray();
            foreach (IJsonSerializable item in list)
            {
                if (item == null)
                {
                    writer.WriteNull();
                }
                else
                {
                    item.WriteJson(writer);
                }
            }
            writer.WriteEndArray();
        }

        public void FromJson(string json)
        {
            JsonReader reader = new JsonTextReader(new StringReader(json));
            ReadJson(reader);
        }

        public bool ReadJson(JsonReader reader)
        {
            while (reader.TokenType != JsonToken.StartArray &&
                reader.TokenType != JsonToken.StartObject &&
                reader.Read()) ;

            if (reader.TokenType != JsonToken.StartArray && reader.TokenType != JsonToken.StartObject) return false;

            while (reader.TokenType != JsonToken.StartObject && reader.TokenType != JsonToken.EndArray && reader.Read()) ;

            while (reader.TokenType == JsonToken.StartObject)
            {
                if (!ReadJsonObject(reader))
                {
                    return false;
                }
                while (reader.Read() && reader.TokenType != JsonToken.StartObject && reader.TokenType != JsonToken.EndArray) ;
            }

            return true;
        }

        public virtual bool ReadJsonObject(JsonReader reader)
        {
            if (constructor != null)
            {
                T t = (T)constructor.Invoke(null);
                if (t.ReadJson(reader))
                {
                    list.Add(t);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                throw new NotImplementedException(typeof(T).Name + "类型没有默认构造函数, 无法从Json反序列化!");
                //return false;
            }
        }

        #endregion
    }
}
